home *** CD-ROM | disk | FTP | other *** search
/ Mac Easy 2010 May / Mac Life Ubuntu.iso / casper / filesystem.squashfs / usr / share / pyshared / checkbox_gtk / gtk_interface.py next >
Encoding:
Python Source  |  2009-04-27  |  10.1 KB  |  314 lines

  1. #
  2. # This file is part of Checkbox.
  3. #
  4. # Copyright 2008 Canonical Ltd.
  5. #
  6. # Checkbox is free software: you can redistribute it and/or modify
  7. # it under the terms of the GNU General Public License as published by
  8. # the Free Software Foundation, either version 3 of the License, or
  9. # (at your option) any later version.
  10. #
  11. # Checkbox is distributed in the hope that it will be useful,
  12. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. # GNU General Public License for more details.
  15. #
  16. # You should have received a copy of the GNU General Public License
  17. # along with Checkbox.  If not, see <http://www.gnu.org/licenses/>.
  18. #
  19. import re
  20. import gtk, gtk.glade
  21. import posixpath
  22.  
  23. from gettext import gettext as _
  24.  
  25. from checkbox.test import ALL_STATUS, TestResult
  26. from checkbox.user_interface import UserInterface
  27.  
  28. # Import to register HyperTextView type with gtk
  29. from checkbox_gtk.hyper_text_view import HyperTextView
  30.  
  31.  
  32. # HACK: Setting and unsetting previous and next buttons to workaround
  33. #       for gnome bug #56070.
  34. class GTKHack(object):
  35.     def __init__(self, function):
  36.         self._function = function
  37.  
  38.     def __get__(self, instance, cls=None):
  39.         self._instance = instance
  40.         return self
  41.  
  42.     def __call__(self, *args, **kwargs):
  43.         self._instance._set_sensitive("button_previous", False)
  44.         self._instance._set_sensitive("button_next", False)
  45.         self._instance._set_sensitive("button_previous", True)
  46.         self._instance._set_sensitive("button_next", True)
  47.         return self._function(self._instance, *args, **kwargs)
  48.  
  49.  
  50. class GTKInterface(UserInterface):
  51.  
  52.     def __init__(self, title, data_path):
  53.         super(GTKInterface, self).__init__(title, data_path)
  54.  
  55.         # Load UI
  56.         gtk.window_set_default_icon_name("checkbox")
  57.         gtk.glade.textdomain(self.gettext_domain)
  58.         self.widgets = gtk.glade.XML(posixpath.join(data_path,
  59.             "checkbox-gtk.glade"))
  60.         self.widgets.signal_autoconnect(self)
  61.  
  62.         # Set background color for head
  63.         eventbox_head = self._get_widget("eventbox_head")
  64.         eventbox_head.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse("white"))
  65.  
  66.         # Set dialog title
  67.         self._dialog = self._get_widget("dialog_main")
  68.         self._dialog.set_title(title)
  69.  
  70.         # Set wait transient for dialog
  71.         self._wait = self._get_widget("window_wait")
  72.         self._wait.set_transient_for(self._dialog)
  73.         self._wait.realize()
  74.         self._wait.window.set_functions(gtk.gdk.FUNC_MOVE)
  75.  
  76.         # Set shorthand for notebook
  77.         self._notebook = self._get_widget("notebook_main")
  78.         self._handler_id = None
  79.  
  80.     def _get_widget(self, widget):
  81.         return self.widgets.get_widget(widget)
  82.  
  83.     def _get_radio_button(self, map):
  84.         for radio_button, value in map.items():
  85.             if self._get_widget(radio_button).get_active():
  86.                 return value
  87.         raise Exception, "Failed to map radio_button."
  88.  
  89.     def _get_text(self, name):
  90.         widget = self._get_widget(name)
  91.         return widget.get_text()
  92.  
  93.     def _get_text_view(self, name):
  94.         widget = self._get_widget(name)
  95.         buffer = widget.get_buffer()
  96.         text = buffer.get_text(buffer.get_start_iter(), buffer.get_end_iter())
  97.         return text
  98.  
  99.     def _set_label(self, name, label=""):
  100.         widget = self._get_widget(name)
  101.         widget.set_label(label)
  102.  
  103.     def _set_text(self, name, text=""):
  104.         widget = self._get_widget(name)
  105.         widget.set_text(text)
  106.  
  107.     def _set_text_view(self, name, text=""):
  108.         buffer = gtk.TextBuffer()
  109.         buffer.set_text(text)
  110.         widget = self._get_widget(name)
  111.         widget.set_buffer(buffer)
  112.  
  113.     def _set_hyper_text_view(self, name, text=""):
  114.         def clicked(widget, text, anchor, button):
  115.             self.show_url(anchor)
  116.  
  117.         widget = self._get_widget(name)
  118.         widget.connect("anchor-clicked", clicked)
  119.  
  120.         buffer = gtk.TextBuffer()
  121.         widget.set_buffer(buffer)
  122.  
  123.         url_regex = r"https?://[^\s]+"
  124.         tag_regex = r"\[\[[^\]]+\]\]"
  125.         in_hyper_text = False
  126.         for part in re.split(r"(%s|%s)" % (url_regex, tag_regex), text):
  127.             if in_hyper_text:
  128.                 in_hyper_text = False
  129.                 anchor = part
  130.                 if re.match("^%s$" % tag_regex, part):
  131.                     part = part.lstrip("[").rstrip("]")
  132.                     if "|" in part:
  133.                         (anchor, part) = part.split("|", 1)
  134.                 widget.insert_with_anchor(part, anchor)
  135.             else:
  136.                 in_hyper_text = True
  137.                 widget.insert(part)
  138.  
  139.     def _set_active(self, name, value=True):
  140.         widget = self._get_widget(name)
  141.         widget.set_active(bool(value))
  142.  
  143.     def _set_show(self, name, value=True):
  144.         widget = self._get_widget(name)
  145.         if value:
  146.             widget.show()
  147.         else:
  148.             widget.hide()
  149.  
  150.     def _set_sensitive(self, name, value=True):
  151.         # Hack to workaround Gnome bug #56070
  152.         self._set_show(name, False)
  153.         self._set_show(name, True)
  154.  
  155.         widget = self._get_widget(name)
  156.         widget.set_sensitive(bool(value))
  157.  
  158.     def _run_dialog(self, dialog=None):
  159.         def on_dialog_response(dialog, response, self):
  160.             self.direction = response
  161.             gtk.main_quit()
  162.  
  163.         dialog = dialog or self._dialog
  164.         dialog.connect("response", on_dialog_response, self)
  165.         dialog.show()
  166.         gtk.main()
  167.         if self.direction == gtk.RESPONSE_DELETE_EVENT:
  168.             raise KeyboardInterrupt
  169.  
  170.     def do_function(self, function, *args, **kwargs):
  171.         self._set_sensitive("button_previous", False)
  172.         self._set_sensitive("button_next", False)
  173.  
  174.         result = super(GTKInterface, self).do_function(function,
  175.             *args, **kwargs)
  176.  
  177.         self._set_sensitive("button_previous", True)
  178.         self._set_sensitive("button_next", True)
  179.  
  180.         return result
  181.  
  182.     def show_wait(self, message, function, *args, **kwargs):
  183.         self._set_text("label_wait", message)
  184.         self._wait.show()
  185.  
  186.         result = self.do_function(function, *args, **kwargs)
  187.  
  188.         self._wait.hide()
  189.         return result
  190.  
  191.     def show_pulse(self):
  192.         self._get_widget("progressbar_wait").pulse()
  193.         while gtk.events_pending():
  194.             gtk.main_iteration()
  195.  
  196.     @GTKHack
  197.     def show_intro(self, title, text):
  198.         # Set buttons
  199.         self._set_sensitive("button_previous", False)
  200.         self._notebook.set_current_page(0)
  201.  
  202.         intro = "\n\n".join([title, text])
  203.         self._set_hyper_text_view("hyper_text_view_intro_text", intro)
  204.  
  205.         self._run_dialog()
  206.  
  207.         self._set_sensitive("button_previous", True)
  208.  
  209.     @GTKHack
  210.     def show_category(self, title, text, category=None):
  211.         # Set buttons
  212.         self._notebook.set_current_page(1)
  213.  
  214.         self._set_hyper_text_view("hyper_text_view_category", text)
  215.         if category:
  216.             self._set_active("radio_button_%s" % category)
  217.  
  218.         self._run_dialog()
  219.  
  220.         return self._get_radio_button({
  221.             "radio_button_desktop": "desktop",
  222.             "radio_button_laptop": "laptop",
  223.             "radio_button_server": "server"})
  224.  
  225.     def _run_test(self, test):
  226.         self._set_sensitive("button_test", False)
  227.  
  228.         message = _("Running test %s...") % test.name
  229.         result = self.show_wait(message, test.command)
  230.  
  231.         description = self.do_function(test.description, result)
  232.         self._set_hyper_text_view("hyper_text_view_test", description)
  233.  
  234.         self._set_sensitive("button_test", True)
  235.         self._set_label("button_test", _("_Test Again"))
  236.  
  237.     @GTKHack
  238.     def show_test(self, test, result=None):
  239.         self._set_sensitive("button_test", False)
  240.         self._notebook.set_current_page(2)
  241.  
  242.         # Set test description
  243.         description = self.do_function(test.description, result)
  244.         self._set_hyper_text_view("hyper_text_view_test", description)
  245.  
  246.         # Set buttons
  247.         if str(test.command):
  248.             self._set_sensitive("button_test", True)
  249.  
  250.             button_test = self._get_widget("button_test")
  251.             if self._handler_id:
  252.                 button_test.disconnect(self._handler_id)
  253.             self._handler_id = button_test.connect("clicked",
  254.                 lambda w, t=test: self._run_test(t))
  255.  
  256.         # Default results
  257.         answers = ["yes", "no", "skip"]
  258.         if result:
  259.             self._set_text_view("text_view_comment", result.data)
  260.             answer = dict(zip(ALL_STATUS, answers))[result.status]
  261.             self._set_active("radio_button_%s" % answer)
  262.         else:
  263.             self._set_text_view("text_view_comment")
  264.             self._set_active("radio_button_skip")
  265.  
  266.         self._run_dialog()
  267.  
  268.         # Reset labels
  269.         self._set_hyper_text_view("hyper_text_view_test")
  270.         self._set_label("button_test", _("_Test"))
  271.  
  272.         radio_buttons = ["radio_button_%s" % a for a in answers]
  273.         status = self._get_radio_button(dict(zip(radio_buttons, ALL_STATUS)))
  274.         data = self._get_text_view("text_view_comment")
  275.         return TestResult(test, status, data)
  276.  
  277.     @GTKHack
  278.     def show_exchange(self, authentication, message=None):
  279.         self._notebook.set_current_page(3)
  280.  
  281.         if authentication is not None:
  282.             self._set_text("entry_authentication", authentication)
  283.  
  284.         if message is not None:
  285.             self._set_hyper_text_view("hyper_text_view_exchange", message)
  286.  
  287.         self._run_dialog()
  288.  
  289.         authentication = self._get_text("entry_authentication")
  290.  
  291.         return authentication
  292.  
  293.     @GTKHack
  294.     def show_final(self, message=None):
  295.         self._set_label("button_next", _("_Finish"))
  296.         self._notebook.set_current_page(4)
  297.  
  298.         if message is not None:
  299.             self._set_hyper_text_view("hyper_text_view_final", message)
  300.  
  301.         self._run_dialog()
  302.  
  303.         self._set_label("button_next", _("Ne_xt"))
  304.  
  305.     def show_error(self, title, text):
  306.         message_dialog = gtk.MessageDialog(parent=self._dialog,
  307.             type=gtk.MESSAGE_ERROR,
  308.             buttons=gtk.BUTTONS_CLOSE,
  309.             message_format=text)
  310.         message_dialog.set_modal(True)
  311.         message_dialog.set_title(title)
  312.         self._run_dialog(message_dialog)
  313.         message_dialog.hide()
  314.